<template>
  <div class="audit-logs">
    <div class="logs-header">
      <h2>📝 审计日志</h2>
      <div class="header-actions">
        <button @click="loadLogs" class="btn btn-secondary">🔄 刷新</button>
        <button @click="exportLogs" class="btn btn-primary">📥 导出日志</button>
      </div>
    </div>
    
    <!-- 筛选器 -->
    <div class="filters">
      <input
        v-model="filters.search"
        type="text"
        class="form-input"
        placeholder="🔍 搜索用户名、操作或资源..."
        @input="handleFilter"
      />
      
      <select v-model="filters.action" @change="handleFilter" class="form-select">
        <option value="">全部操作</option>
        <option value="login">登录</option>
        <option value="logout">登出</option>
        <option value="create_token">创建令牌</option>
        <option value="update_token">更新令牌</option>
        <option value="delete_token">删除令牌</option>
        <option value="generate_code">生成验证码</option>
        <option value="change_password">修改密码</option>
        <option value="update_user">更新用户</option>
      </select>
      
      <select v-model="filters.status" @change="handleFilter" class="form-select">
        <option value="">全部状态</option>
        <option value="success">成功</option>
        <option value="failure">失败</option>
        <option value="error">错误</option>
      </select>
      
      <input
        v-model="filters.dateFrom"
        type="date"
        class="form-input"
        @change="handleFilter"
      />
      
      <input
        v-model="filters.dateTo"
        type="date"
        class="form-input"
        @change="handleFilter"
      />
    </div>
    
    <!-- 快速筛选 -->
    <div class="quick-filters">
      <button @click="setQuickFilter('today')" class="quick-btn" :class="{ active: quickFilter === 'today' }">
        今日
      </button>
      <button @click="setQuickFilter('week')" class="quick-btn" :class="{ active: quickFilter === 'week' }">
        本周
      </button>
      <button @click="setQuickFilter('month')" class="quick-btn" :class="{ active: quickFilter === 'month' }">
        本月
      </button>
      <button @click="setQuickFilter('security')" class="quick-btn" :class="{ active: quickFilter === 'security' }">
        🔒 安全事件
      </button>
    </div>
    
    <!-- 统计信息 -->
    <div class="stats-bar">
      <div class="stat-item">
        <span class="stat-label">总日志:</span>
        <span class="stat-value">{{ totalLogs }}</span>
      </div>
      <div class="stat-item">
        <span class="stat-label">当前筛选:</span>
        <span class="stat-value">{{ logs.length }}</span>
      </div>
      <div class="stat-item success">
        <span class="stat-label">成功:</span>
        <span class="stat-value">{{ successCount }}</span>
      </div>
      <div class="stat-item failure">
        <span class="stat-label">失败:</span>
        <span class="stat-value">{{ failureCount }}</span>
      </div>
    </div>
    
    <!-- 日志列表 -->
    <div v-if="!loading" class="logs-list">
      <div v-for="log in logs" :key="log.id" class="log-item" :class="`status-${log.status}`">
        <div class="log-icon">
          {{ getActionIcon(log.action) }}
        </div>
        
        <div class="log-content">
          <div class="log-header">
            <div class="log-main">
              <strong class="log-user">{{ log.username || log.userId || '系统' }}</strong>
              <span class="log-action">{{ getActionText(log.action) }}</span>
              <span v-if="log.resourceType" class="log-resource">
                {{ log.resourceType }}: {{ log.resourceId }}
              </span>
            </div>
            <div class="log-meta">
              <span class="log-time">{{ formatDate(log.createdAt) }}</span>
              <span class="log-status" :class="`badge badge-${log.status}`">
                {{ getStatusText(log.status) }}
              </span>
            </div>
          </div>
          
          <div class="log-details">
            <span v-if="log.ipAddress" class="detail-item">
              🌐 {{ log.ipAddress }}
            </span>
            <span v-if="log.userAgent" class="detail-item" :title="log.userAgent">
              💻 {{ getBrowserInfo(log.userAgent) }}
            </span>
          </div>
          
          <div v-if="log.details" class="log-extra">
            <button @click="toggleDetails(log.id)" class="details-btn">
              {{ expandedLogs.has(log.id) ? '▼ 收起详情' : '▶ 展开详情' }}
            </button>
            <div v-if="expandedLogs.has(log.id)" class="details-content">
              <pre>{{ formatDetails(log.details) }}</pre>
            </div>
          </div>
        </div>
      </div>
      
      <div v-if="logs.length === 0" class="empty-state">
        <div class="empty-icon">📭</div>
        <p>没有找到日志记录</p>
      </div>
      
      <!-- 分页 -->
      <div v-if="totalPages > 1" class="pagination">
        <button
          @click="goToPage(currentPage - 1)"
          :disabled="currentPage === 1"
          class="btn btn-sm"
        >
          ← 上一页
        </button>
        
        <span class="page-info">
          第 {{ currentPage }} / {{ totalPages }} 页
        </span>
        
        <button
          @click="goToPage(currentPage + 1)"
          :disabled="currentPage === totalPages"
          class="btn btn-sm"
        >
          下一页 →
        </button>
      </div>
    </div>
    
    <div v-else class="loading">
      <div class="spinner"></div>
      <p>加载日志中...</p>
    </div>
  </div>
</template>

<script setup>
import { ref, reactive, computed, onMounted } from 'vue';
import api from '@/api';

const loading = ref(false);
const logs = ref([]);
const totalLogs = ref(0);
const currentPage = ref(1);
const pageSize = ref(20);
const quickFilter = ref('');
const expandedLogs = ref(new Set());

const filters = reactive({
  search: '',
  action: '',
  status: '',
  dateFrom: '',
  dateTo: '',
});

const totalPages = computed(() => Math.ceil(totalLogs.value / pageSize.value));

const successCount = computed(() => logs.value.filter(l => l.status === 'success').length);
const failureCount = computed(() => logs.value.filter(l => l.status === 'failure' || l.status === 'error').length);

const actionIcons = {
  login: '🔓',
  logout: '🔒',
  create_token: '➕',
  update_token: '✏️',
  delete_token: '🗑️',
  generate_code: '🔑',
  change_password: '🔐',
  update_user: '👤',
  disable_user: '🚫',
  enable_user: '✅',
  default: '📝',
};

const actionTexts = {
  login: '登录',
  logout: '登出',
  create_token: '创建令牌',
  update_token: '更新令牌',
  delete_token: '删除令牌',
  generate_code: '生成验证码',
  change_password: '修改密码',
  update_user: '更新用户信息',
  disable_user: '禁用用户',
  enable_user: '启用用户',
};

function getActionIcon(action) {
  return actionIcons[action] || actionIcons.default;
}

function getActionText(action) {
  return actionTexts[action] || action;
}

function getStatusText(status) {
  const statusMap = {
    success: '成功',
    failure: '失败',
    error: '错误',
  };
  return statusMap[status] || status;
}

function getBrowserInfo(userAgent) {
  if (!userAgent) return '未知';
  if (userAgent.includes('Chrome')) return 'Chrome';
  if (userAgent.includes('Firefox')) return 'Firefox';
  if (userAgent.includes('Safari')) return 'Safari';
  if (userAgent.includes('Edge')) return 'Edge';
  return '其他浏览器';
}

function formatDate(dateString) {
  if (!dateString) return '-';
  const date = new Date(dateString);
  const now = new Date();
  const diff = now - date;
  
  // 1分钟内
  if (diff < 60000) {
    return '刚刚';
  }
  // 1小时内
  if (diff < 3600000) {
    return Math.floor(diff / 60000) + '分钟前';
  }
  // 24小时内
  if (diff < 86400000) {
    return Math.floor(diff / 3600000) + '小时前';
  }
  
  return date.toLocaleString('zh-CN');
}

function formatDetails(details) {
  if (!details) return '';
  if (typeof details === 'string') {
    try {
      return JSON.stringify(JSON.parse(details), null, 2);
    } catch {
      return details;
    }
  }
  return JSON.stringify(details, null, 2);
}

function toggleDetails(logId) {
  if (expandedLogs.value.has(logId)) {
    expandedLogs.value.delete(logId);
  } else {
    expandedLogs.value.add(logId);
  }
}

function setQuickFilter(filter) {
  quickFilter.value = filter;
  const now = new Date();
  
  switch (filter) {
    case 'today':
      filters.dateFrom = now.toISOString().split('T')[0];
      filters.dateTo = now.toISOString().split('T')[0];
      break;
    case 'week':
      const weekAgo = new Date(now - 7 * 24 * 60 * 60 * 1000);
      filters.dateFrom = weekAgo.toISOString().split('T')[0];
      filters.dateTo = now.toISOString().split('T')[0];
      break;
    case 'month':
      const monthAgo = new Date(now - 30 * 24 * 60 * 60 * 1000);
      filters.dateFrom = monthAgo.toISOString().split('T')[0];
      filters.dateTo = now.toISOString().split('T')[0];
      break;
    case 'security':
      filters.action = 'login';
      filters.status = 'failure';
      break;
  }
  
  handleFilter();
}

async function loadLogs() {
  loading.value = true;
  try {
    const params = {
      page: currentPage.value,
      limit: pageSize.value,
      ...filters,
    };
    
    const response = await api.get('/admin/logs', { params });
    logs.value = response.data.data.logs || [];
    totalLogs.value = response.data.data.total || 0;
  } catch (error) {
    console.error('加载日志失败:', error);
    alert('加载日志失败');
  } finally {
    loading.value = false;
  }
}

function handleFilter() {
  currentPage.value = 1;
  loadLogs();
}

function goToPage(page) {
  if (page >= 1 && page <= totalPages.value) {
    currentPage.value = page;
    loadLogs();
  }
}

async function exportLogs() {
  try {
    const response = await api.get('/admin/logs/export', {
      params: filters,
      responseType: 'blob',
    });
    
    const url = window.URL.createObjectURL(new Blob([response.data]));
    const link = document.createElement('a');
    link.href = url;
    link.setAttribute('download', `audit_logs_${new Date().toISOString().split('T')[0]}.csv`);
    document.body.appendChild(link);
    link.click();
    link.remove();
    
    alert('日志导出成功');
  } catch (error) {
    alert('导出失败: ' + (error.response?.data?.error?.message || error.message));
  }
}

onMounted(() => {
  loadLogs();
});
</script>

<style scoped>
.audit-logs {
  background: var(--bg-color, #fff);
  border-radius: 12px;
  padding: 30px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.logs-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 24px;
}

.logs-header h2 {
  font-size: 24px;
  color: var(--text-color, #333);
  margin: 0;
}

.header-actions {
  display: flex;
  gap: 12px;
}

.filters {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1fr 1fr;
  gap: 12px;
  margin-bottom: 16px;
}

.form-input,
.form-select {
  padding: 10px 14px;
  border: 1px solid var(--border-color, #d1d5db);
  border-radius: 8px;
  font-size: 14px;
  color: var(--text-color, #333);
  background: var(--bg-color, #fff);
}

.quick-filters {
  display: flex;
  gap: 8px;
  margin-bottom: 16px;
}

.quick-btn {
  padding: 8px 16px;
  border: 1px solid var(--border-color, #d1d5db);
  border-radius: 6px;
  background: var(--bg-color, #fff);
  color: var(--text-color, #333);
  font-size: 14px;
  cursor: pointer;
  transition: all 0.2s;
}

.quick-btn:hover {
  border-color: var(--primary-color, #3b82f6);
  color: var(--primary-color, #3b82f6);
}

.quick-btn.active {
  background: var(--primary-color, #3b82f6);
  border-color: var(--primary-color, #3b82f6);
  color: white;
}

.stats-bar {
  display: flex;
  gap: 24px;
  padding: 16px;
  background: var(--bg-secondary, #f9fafb);
  border-radius: 8px;
  margin-bottom: 20px;
}

.stat-item {
  display: flex;
  gap: 8px;
  align-items: center;
}

.stat-label {
  font-size: 14px;
  color: var(--text-secondary, #6b7280);
}

.stat-value {
  font-size: 16px;
  font-weight: bold;
  color: var(--text-color, #333);
}

.stat-item.success .stat-value {
  color: #10b981;
}

.stat-item.failure .stat-value {
  color: #ef4444;
}

.logs-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.log-item {
  display: flex;
  gap: 16px;
  padding: 16px;
  background: var(--bg-color, #fff);
  border: 1px solid var(--border-color, #e5e7eb);
  border-left: 4px solid var(--border-color, #e5e7eb);
  border-radius: 8px;
  transition: all 0.2s;
}

.log-item:hover {
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.log-item.status-success {
  border-left-color: #10b981;
}

.log-item.status-failure,
.log-item.status-error {
  border-left-color: #ef4444;
}

.log-icon {
  font-size: 24px;
  flex-shrink: 0;
}

.log-content {
  flex: 1;
  min-width: 0;
}

.log-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 8px;
  gap: 16px;
}

.log-main {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}

.log-user {
  color: var(--text-color, #333);
}

.log-action {
  color: var(--text-secondary, #6b7280);
}

.log-resource {
  font-size: 13px;
  color: var(--text-secondary, #6b7280);
  background: var(--bg-secondary, #f3f4f6);
  padding: 2px 8px;
  border-radius: 4px;
}

.log-meta {
  display: flex;
  gap: 12px;
  align-items: center;
  flex-shrink: 0;
}

.log-time {
  font-size: 13px;
  color: var(--text-secondary, #6b7280);
  white-space: nowrap;
}

.log-status {
  font-size: 12px;
}

.badge {
  padding: 4px 8px;
  border-radius: 4px;
  font-weight: 500;
}

.badge-success {
  background: #d1fae5;
  color: #065f46;
}

.badge-failure,
.badge-error {
  background: #fee2e2;
  color: #991b1b;
}

.log-details {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 8px;
}

.detail-item {
  font-size: 13px;
  color: var(--text-secondary, #6b7280);
}

.log-extra {
  margin-top: 12px;
}

.details-btn {
  padding: 6px 12px;
  border: 1px solid var(--border-color, #d1d5db);
  border-radius: 6px;
  background: var(--bg-secondary, #f9fafb);
  color: var(--text-color, #333);
  font-size: 13px;
  cursor: pointer;
  transition: all 0.2s;
}

.details-btn:hover {
  background: var(--border-color, #e5e7eb);
}

.details-content {
  margin-top: 12px;
  padding: 12px;
  background: var(--bg-secondary, #f9fafb);
  border-radius: 6px;
  overflow-x: auto;
}

.details-content pre {
  margin: 0;
  font-size: 12px;
  color: var(--text-secondary, #6b7280);
  white-space: pre-wrap;
  word-break: break-word;
}

.pagination {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 16px;
  margin-top: 24px;
  padding: 16px;
}

.page-info {
  color: var(--text-secondary, #6b7280);
}

.btn {
  padding: 10px 20px;
  border: none;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.2s;
}

.btn-primary {
  background: var(--primary-color, #3b82f6);
  color: white;
}

.btn-primary:hover {
  background: var(--primary-dark, #2563eb);
}

.btn-secondary {
  background: var(--bg-secondary, #f3f4f6);
  color: var(--text-color, #333);
}

.btn-secondary:hover {
  background: var(--border-color, #e5e7eb);
}

.btn-sm {
  padding: 8px 16px;
  font-size: 13px;
}

.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.empty-state {
  text-align: center;
  padding: 80px 20px;
}

.empty-icon {
  font-size: 64px;
  margin-bottom: 16px;
}

.empty-state p {
  color: var(--text-secondary, #6b7280);
}

.loading {
  text-align: center;
  padding: 80px 20px;
}

.spinner {
  width: 40px;
  height: 40px;
  margin: 0 auto 16px;
  border: 4px solid var(--bg-secondary, #f3f4f6);
  border-top-color: var(--primary-color, #3b82f6);
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* 深色模式 */
.dark-theme .audit-logs {
  background: #1f2937;
}

.dark-theme .log-item {
  background: #1f2937;
  border-color: #374151;
}

.dark-theme .stats-bar {
  background: #111827;
}

.dark-theme .form-input,
.dark-theme .form-select {
  background: #111827;
  border-color: #374151;
  color: #e5e7eb;
}

.dark-theme .quick-btn {
  background: #111827;
  border-color: #374151;
}

.dark-theme .details-btn,
.dark-theme .details-content {
  background: #111827;
  border-color: #374151;
}

.dark-theme .badge-success {
  background: #064e3b;
  color: #6ee7b7;
}

.dark-theme .badge-failure,
.dark-theme .badge-error {
  background: #7f1d1d;
  color: #fca5a5;
}

/* 响应式 */
@media (max-width: 1024px) {
  .filters {
    grid-template-columns: 1fr;
  }
  
  .log-header {
    flex-direction: column;
    align-items: flex-start;
  }
  
  .log-meta {
    width: 100%;
    justify-content: space-between;
  }
}

@media (max-width: 768px) {
  .header-actions {
    flex-direction: column;
    width: 100%;
  }
  
  .header-actions .btn {
    width: 100%;
  }
  
  .quick-filters {
    flex-wrap: wrap;
  }
  
  .stats-bar {
    flex-wrap: wrap;
  }
}
</style>


